package com.iotp.service.organization;

import com.iotp.dao.organization.OrganizationDAO;
import com.iotp.entity.organization.Organization;
import com.iotp.service.base.BaseServiceImpl;
import com.iotp.utils.common.DataUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;

/**
 * 系统机构业务接口实现类
 * @author Assassin
 */
@Service("organizationService")
public class OrganizationServiceImpl extends BaseServiceImpl implements OrganizationService {

	// Fields

	@Autowired
	private OrganizationDAO organizationDAO;// 系统机构DAO接口

	// Methods

	/**
	* 添加系统机构根机构
	* @param orgType 标识信息-机构类型
	* @param orgName 基本信息-机构名称
	* @param orgAliasName 基本信息-机构别名
	* @param orgDesc 基本信息-机构说明
	* @param orgPhone 基本信息-机构电话
	* @param orgFax 基本信息-机构传真
	* @param orgWebsite 基本信息-机构网址
	* @param provinceId 位置信息-机构省Id
	* @param cityId 位置信息-机构市Id
	* @param districtId 位置信息-机构区Id
	* @param orgAddress 位置信息-机构地址
	* @param lng 位置信息-机构经度
	* @param lat 位置信息-机构纬度
	* @param orgManagerId 管理信息-机构负责人Id
	* @param orgManagerName 管理信息-机构负责人名称
	* @param orgManagerPhone 管理信息-机构负责人电话
	* @return Long orgId 添加后的数据库主键值
	*/
	public Long addRoot(Integer orgType, String orgName, String orgAliasName, String orgDesc, String orgPhone,
			String orgFax, String orgWebsite, String provinceId, String cityId, String districtId, String orgAddress,
			BigDecimal lng, BigDecimal lat, Long orgManagerId, String orgManagerName, String orgManagerPhone) {
		// 构造系统机构参数实体
		Organization organization = new Organization();
		
		// 标识信息
		String orgCode = DataUtil.getOrgCode(queryCurrentMaxOrgCode(1, 0L), null);// 添加根机构orgLeve=1 & orgPid=0L
		organization.setOrgCode(orgCode);// Set 标识信息-机构编码
		organization.setOrgType(orgType);// Set 标识信息-机构类型
		
		// 状态信息
		organization.setOrgStatus(1);// Set 状态信息-机构数据状态->默认数据状态=>1
		organization.setIsDel(0);// Set 状态信息-是否删除[1-是 | 0-否]->默认是否删除=>0
		organization.setOrgOrder(null);// Set 状态信息-机构排序->默认排序=>null
		
		// 层级信息
		organization.setOrgLevel(1);// Set 层级信息-机构层级->添加根机构默认级别=>1
		organization.setIsParent(0);// Set 层级信息-是否父级[1-是 | 0-否]->新添加机构默认是否父级=>0
		organization.setOrgPid(0L);// Set 层级信息-父级Id[ROOT-0]->添加根机构默认父级Id=>0L
		
		// 基本信息
		organization.setOrgName(orgName);// Set 基本信息-机构名称
		organization.setOrgAliasName(orgAliasName);// Set 基本信息-机构别名
		organization.setOrgDesc(orgDesc);// Set 基本信息-机构说明
		organization.setOrgPhone(orgPhone);// Set 基本信息-机构电话
		organization.setOrgFax(orgFax);// Set 基本信息-机构传真
		organization.setOrgWebsite(orgWebsite);// Set 基本信息-机构网址
		
		// 位置信息
		organization.setProvinceId(provinceId);// Set 位置信息-机构省Id
		organization.setCityId(cityId);// Set 位置信息-机构市Id
		organization.setDistrictId(districtId);// Set 位置信息-机构区Id
		organization.setOrgAddress(orgAddress);// Set 位置信息-机构地址
		organization.setLng(lng);// Set 位置信息-机构经度
		organization.setLat(lat);// Set 位置信息-机构纬度
		
		// 管理信息
		organization.setOrgManagerId(orgManagerId);// Set 管理信息-机构负责人Id
		organization.setOrgManagerName(orgManagerName);// Set 管理信息-机构负责人名称
		organization.setOrgManagerPhone(orgManagerPhone);// Set 管理信息-机构负责人电话
		
		// 时间信息
		Long createTime = System.currentTimeMillis();// 默认创建时间->系统当前时间
		organization.setCreateTime(createTime);// Set 时间信息-创建时间
		organization.setUpdateTime(null);// Set 时间信息-更新时间[初始化=NULL]
		
		// 调用系统机构DAO接口
		this.organizationDAO.insert(organization);
		
		// 返回添加后的数据库主键值
		return organization.getOrgId();
	}
	
   /**
	* 添加系统机构子机构
	* @param orgPid 层级信息-机构父级Id
	* @param orgName 基本信息-机构名称
	* @param orgAliasName 基本信息-机构别名
	* @param orgDesc 基本信息-机构说明
	* @param orgPhone 基本信息-机构电话
	* @param orgFax 基本信息-机构传真
	* @param orgWebsite 基本信息-机构网址
	* @param provinceId 位置信息-机构省Id
	* @param cityId 位置信息-机构市Id
	* @param districtId 位置信息-机构区Id
	* @param orgAddress 位置信息-机构地址
	* @param lng 位置信息-机构经度
	* @param lat 位置信息-机构纬度
	* @param orgManagerId 管理信息-机构负责人Id
	* @param orgManagerName 管理信息-机构负责人名称
	* @param orgManagerPhone 管理信息-机构负责人电话
	* @return Long orgId 添加后的数据库主键值
	*/
	@Override
	public Long addSub(Long orgPid, String orgName, String orgAliasName, String orgDesc, String orgPhone,
			String orgFax, String orgWebsite, String provinceId, String cityId, String districtId, String orgAddress,
			BigDecimal lng, BigDecimal lat, Long orgManagerId, String orgManagerName, String orgManagerPhone) {
		// 构造系统机构参数实体
		Organization organization = new Organization();
		
		// 查询父机构信息
		Organization parentOrg = this.organizationDAO.selectById(orgPid);
		Integer orgLevel = parentOrg.getOrgLevel() + 1;// 根据父机构Id计算当前子机构级别
		
		// 标识信息
		String orgCode = DataUtil.getOrgCode(queryCurrentMaxOrgCode(orgLevel, orgPid), parentOrg.getOrgCode());
		organization.setOrgCode(orgCode);// Set 标识信息-机构编码
		organization.setOrgType(parentOrg.getOrgType());// Set 标识信息-机构类型
		
		// 状态信息
		organization.setOrgStatus(1);// Set 状态信息-机构数据状态->默认数据状态=>1
		organization.setIsDel(0);// Set 状态信息-是否删除[1-是 | 0-否]->默认是否删除=>0
		organization.setOrgOrder(null);// Set 状态信息-机构排序->默认排序=>null
		
		// 层级信息
		organization.setOrgLevel(orgLevel);// Set 层级信息-机构层级->添加子机构级别=>orgLevel
		organization.setIsParent(0);// Set 层级信息-是否父级[1-是 | 0-否]->新添加机构默认是否父级=>0
		organization.setOrgPid(orgPid);// Set 层级信息-父级Id[ROOT-0]->添加子机构父级Id=>orgPid
		
		// 基本信息
		organization.setOrgName(orgName);// Set 基本信息-机构名称
		organization.setOrgAliasName(orgAliasName);// Set 基本信息-机构别名
		organization.setOrgDesc(orgDesc);// Set 基本信息-机构说明
		organization.setOrgPhone(orgPhone);// Set 基本信息-机构电话
		organization.setOrgFax(orgFax);// Set 基本信息-机构传真
		organization.setOrgWebsite(orgWebsite);// Set 基本信息-机构网址
		
		// 位置信息
		organization.setProvinceId(provinceId);// Set 位置信息-机构省Id
		organization.setCityId(cityId);// Set 位置信息-机构市Id
		organization.setDistrictId(districtId);// Set 位置信息-机构区Id
		organization.setOrgAddress(orgAddress);// Set 位置信息-机构地址
		organization.setLng(lng);// Set 位置信息-机构经度
		organization.setLat(lat);// Set 位置信息-机构纬度
		
		// 管理信息
		organization.setOrgManagerId(orgManagerId);// Set 管理信息-机构负责人Id
		organization.setOrgManagerName(orgManagerName);// Set 管理信息-机构负责人名称
		organization.setOrgManagerPhone(orgManagerPhone);// Set 管理信息-机构负责人电话
		
		// 时间信息
		Long createTime = System.currentTimeMillis();// 默认创建时间->系统当前时间
		organization.setCreateTime(createTime);// Set 时间信息-创建时间
		organization.setUpdateTime(null);// Set 时间信息-更新时间[初始化=NULL]
		
		// 调用系统机构DAO接口
		this.organizationDAO.insert(organization);
		
		// 子机构添加成功，更新父级机构信息
		if(parentOrg.getIsParent().intValue() == 0) {
			editIsParent(parentOrg.getOrgId(), 1);
		}
		
		// 返回添加后的数据库主键值
		return organization.getOrgId();
	}

   /**
	* 删除系统机构
	* @param orgId 主键值
	*/
	@Override
	public void delete(Long orgId) {
		// 调用系统机构DAO接口
		this.organizationDAO.delete(orgId);
	}

   /**
	* 更新系统机构
	* @param orgId 标识信息-机构Id
	* @param orgStatus 状态信息-机构数据状态
	* @param isDel 状态信息-是否删除[1-是 | 0-否]
	* @param orgOrder 状态信息-机构排序
	* @param orgName 基本信息-机构名称
	* @param orgAliasName 基本信息-机构别名
	* @param orgDesc 基本信息-机构说明
	* @param orgPhone 基本信息-机构电话
	* @param orgFax 基本信息-机构传真
	* @param orgWebsite 基本信息-机构网址
	* @param provinceId 位置信息-机构省Id
	* @param cityId 位置信息-机构市Id
	* @param districtId 位置信息-机构区Id
	* @param orgAddress 位置信息-机构地址
	* @param lng 位置信息-机构经度
	* @param lat 位置信息-机构纬度
	* @param orgManagerId 管理信息-机构负责人Id
	* @param orgManagerName 管理信息-机构负责人名称
	* @param orgManagerPhone 管理信息-机构负责人电话
	*/
	@Override
	public void edit(Long orgId, Integer orgStatus, Integer isDel, Integer orgOrder, String orgName, String orgAliasName, String orgDesc, String orgPhone,
			String orgFax, String orgWebsite, String provinceId, String cityId, String districtId, String orgAddress,
			BigDecimal lng, BigDecimal lat, Long orgManagerId, String orgManagerName, String orgManagerPhone) {
		// 构造系统机构参数实体
		Organization organization = new Organization();
		organization.setOrgId(orgId);// Set 标识信息-机构Id[主键值]
		organization.setOrgStatus(orgStatus);// Set 状态信息-机构数据状态
		organization.setOrgName(orgName);// Set 基本信息-机构名称
		organization.setOrgAliasName(orgAliasName);// Set 基本信息-机构别名
		organization.setOrgDesc(orgDesc);// Set 基本信息-机构说明
		organization.setOrgPhone(orgPhone);// Set 基本信息-机构电话
		organization.setOrgFax(orgFax);// Set 基本信息-机构传真
		organization.setOrgWebsite(orgWebsite);// Set 基本信息-机构网址
		organization.setProvinceId(provinceId);// Set 位置信息-机构省Id
		organization.setCityId(cityId);// Set 位置信息-机构市Id
		organization.setDistrictId(districtId);// Set 位置信息-机构区Id
		organization.setOrgAddress(orgAddress);// Set 位置信息-机构地址
		organization.setLng(lng);// Set 位置信息-机构经度
		organization.setLat(lat);// Set 位置信息-机构纬度
		organization.setOrgManagerId(orgManagerId);// Set 管理信息-机构负责人Id
		organization.setOrgManagerName(orgManagerName);// Set 管理信息-机构负责人名称
		organization.setOrgManagerPhone(orgManagerPhone);// Set 管理信息-机构负责人电话
		organization.setUpdateTime(System.currentTimeMillis());// Set 时间信息-更新时间[初始化=NULL]
		// 调用系统机构DAO接口
		this.organizationDAO.update(organization);
	}

   /**
	* 主键查询系统机构
	* @param organization 参数实体
	* @return Organization 实体
	*/
	@Override
	public Organization queryById(Long orgId) {
		// 调用系统机构DAO接口
		return this.organizationDAO.selectById(orgId);
	}

   /**
	* 根据条件查询系统机构列表
	* @param orgId 标识信息-机构Id[主键值]
	* @param orgCode 标识信息-机构编码
	* @param orgType 标识信息-机构类型
	* @param orgStatus 状态信息-机构数据状态
	* @param isDel 状态信息-是否删除[1-是 | 0-否]
	* @param orgOrder 状态信息-机构排序
	* @param orgLevel 层级信息-机构层级
	* @param isParent 层级信息-是否父级[1-是 | 0-否]
	* @param orgPid 层级信息-父级Id[ROOT-0]
	* @param orgName 基本信息-机构名称
	* @param orgAliasName 基本信息-机构别名
	* @param orgDesc 基本信息-机构说明
	* @param orgPhone 基本信息-机构电话
	* @param orgFax 基本信息-机构传真
	* @param orgWebsite 基本信息-机构网址
	* @param provinceId 位置信息-机构省Id
	* @param cityId 位置信息-机构市Id
	* @param districtId 位置信息-机构区Id
	* @param orgAddress 位置信息-机构地址
	* @param lng 位置信息-机构经度
	* @param lat 位置信息-机构纬度
	* @param orgManagerId 管理信息-机构负责人Id
	* @param orgManagerName 管理信息-机构负责人名称
	* @param orgManagerPhone 管理信息-机构负责人电话
	* @param createTime 时间信息-创建时间
	* @param updateTime 时间信息-更新时间[初始化=NULL]
	* @return List<Organization> 实体List
	*/
	@Override
	public List<Organization> queryList(Long orgId, String orgCode, Integer orgType, Integer orgStatus, Integer isDel, Integer orgOrder, Integer orgLevel, Integer isParent, Long orgPid, String orgName, String orgAliasName, String orgDesc, String orgPhone, String orgFax, String orgWebsite, String provinceId, String cityId, String districtId, String orgAddress, BigDecimal lng, BigDecimal lat, Long orgManagerId, String orgManagerName, String orgManagerPhone, Long createTime, Long updateTime) {
		// 构造系统机构参数实体
		Organization organization = new Organization();
		organization.setOrgId(orgId);// Set 标识信息-机构Id[主键值]
		organization.setOrgCode(orgCode);// Set 标识信息-机构编码
		organization.setOrgType(orgType);// Set 标识信息-机构类型
		organization.setOrgStatus(orgStatus);// Set 状态信息-机构数据状态
		organization.setIsDel(isDel);// Set 状态信息-是否删除[1-是 | 0-否]
		organization.setOrgOrder(orgOrder);// Set 状态信息-机构排序
		organization.setOrgLevel(orgLevel);// Set 层级信息-机构层级
		organization.setIsParent(isParent);// Set 层级信息-是否父级[1-是 | 0-否]
		organization.setOrgPid(orgPid);// Set 层级信息-父级Id[ROOT-0]
		organization.setOrgName(orgName);// Set 基本信息-机构名称
		organization.setOrgAliasName(orgAliasName);// Set 基本信息-机构别名
		organization.setOrgDesc(orgDesc);// Set 基本信息-机构说明
		organization.setOrgPhone(orgPhone);// Set 基本信息-机构电话
		organization.setOrgFax(orgFax);// Set 基本信息-机构传真
		organization.setOrgWebsite(orgWebsite);// Set 基本信息-机构网址
		organization.setProvinceId(provinceId);// Set 位置信息-机构省Id
		organization.setCityId(cityId);// Set 位置信息-机构市Id
		organization.setDistrictId(districtId);// Set 位置信息-机构区Id
		organization.setOrgAddress(orgAddress);// Set 位置信息-机构地址
		organization.setLng(lng);// Set 位置信息-机构经度
		organization.setLat(lat);// Set 位置信息-机构纬度
		organization.setOrgManagerId(orgManagerId);// Set 管理信息-机构负责人Id
		organization.setOrgManagerName(orgManagerName);// Set 管理信息-机构负责人名称
		organization.setOrgManagerPhone(orgManagerPhone);// Set 管理信息-机构负责人电话
		organization.setCreateTime(createTime);// Set 时间信息-创建时间
		organization.setUpdateTime(updateTime);// Set 时间信息-更新时间[初始化=NULL]
		// 调用系统机构DAO接口
		return this.organizationDAO.selectList(organization);
	}
	
	/**
	 * 编辑机构状态（逻辑删除 | 恢复）
	 * @param orgId 机构Id
	 * @param isDel 是否删除状态
	 */
	@Override
	public void editIsDel(Long orgId, Integer isDel) {
		// 删除前加载出菜单信息
		Organization org = this.organizationDAO.selectById(orgId);
		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		paramsMap.put("orgId", orgId);
		paramsMap.put("isDel", isDel);
		paramsMap.put("updateTime", System.currentTimeMillis());
		this.organizationDAO.updateIsDel(paramsMap);
		// 逻辑删除
		if(isDel.intValue() == 1) {
			// 更新父级机构信息
			if(org.getOrgPid() != null && org.getOrgPid().longValue() != 0L) {
				List<Organization> psubList = querySubList(org.getOrgPid());
				if(psubList == null || psubList.size() == 0) {
					this.editIsParent(org.getOrgPid(), 0);
				}
			}
			// 更新子级机构信息->同步所有子机构删除状态
			if(org.getIsParent().intValue() == 1) {
				HashMap<String, Object> subParamsMap = new HashMap<String, Object>();
				subParamsMap.put("orgPid", org.getOrgId());
				subParamsMap.put("isDel", isDel);
				subParamsMap.put("updateTime", System.currentTimeMillis());
				this.organizationDAO.updateIsDelByPid(subParamsMap);
			}
			// 所有子集都删除后，更新自身是否父级属性
			this.editIsParent(orgId, 0);
		}
	}
	
	/**
	 * 根据父Id查询子机构信息
	 * @param orgPid 父机构Id
	 * @return List<Organization>
	 */
	@Override
	public List<Organization> querySubList(Long orgPid) {
		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		paramsMap.put("orgPid", orgPid);
		paramsMap.put("isDel", 0);
		return this.organizationDAO.selectSubList(paramsMap);
	}
	
	/**
	 * 查询用户机构信息
	 * @param userId 用户Id
	 * @return List<Organization>
	 */
	@Override
	public List<Organization> queryUserOrgs(Long userId) {
		return this.organizationDAO.selectUserOrgs(userId);
	}
	
	/**
	 * 根据机构级别和父机构Id查询当前数据库机构最大编码
	 * @param orgLevel
	 * @param orgPid
	 * @return currentMaxOrgCode
	 */
	private String queryCurrentMaxOrgCode(Integer orgLevel, Long orgPid) {
		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		paramsMap.put("orgLevel", orgLevel);
		paramsMap.put("orgPid", orgPid);
		return this.organizationDAO.selectCurrentMaxOrgCode(paramsMap);
	}

	/**
	 * 更新机构是否父级信息
	 * @param orgId 机构Id
	 * @param isParent 是否父级
	 */
	private void editIsParent(Long orgId, Integer isParent) {
		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		paramsMap.put("orgId", orgId);
		paramsMap.put("isParent", isParent);
		paramsMap.put("updateTime", System.currentTimeMillis());
		this.organizationDAO.updateIsParent(paramsMap);
	}
	
}